package db.nio.worker;

import db.nio.Decoder;
import db.nio.Encoder;
import db.nio.Framer;
import db.nio.Processor;
import db.nio.handler.FrontHandler;

import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 前台接待（接收连接线程)
 * Created by daibin on 10/27/16.
 */
public class FrontWorker extends Worker {

    /**
     * 员工列表
     */
    private List<Worker> backWorkerList;

    /**
     * 处理接口
     */
    private Processor processor;

    /**
     * 编码接口
     */
    private Encoder encoder;

    /**
     * 解码接口
     */
    private Decoder decoder;

    /**
     * 协议封装接口
     */
    private Class<? extends Framer> framerClass;

    /**
     * 最新后台处理
     */
    private int index = 0;


    /**
     * 构造函数
     *
     * @param poolExecutor    线程池
     * @param backWorkerList 后台员工列表
     * @param processor       处理接口
     * @param encoder         编码接口
     * @param decoder         解码接口
     * @param framerClass     协议封装接口
     */
    public FrontWorker(ThreadPoolExecutor poolExecutor, List<Worker> backWorkerList, Processor processor, Encoder encoder, Decoder decoder, Class<? extends Framer> framerClass) {
        super(poolExecutor);
        this.backWorkerList = backWorkerList;
        this.processor = processor;
        this.encoder = encoder;
        this.decoder = decoder;
        this.framerClass = framerClass;
    }

    /**
     * @param key
     */
    @Override
    public void work(SelectionKey key) {
        try {
            if (key.isAcceptable()) {

                //接受连接并交给连接处理器
                ServerSocketChannel server = (ServerSocketChannel) key.channel();
                final SocketChannel channel = server.accept();
                if (channel == null)
                    return;
                channel.configureBlocking(false);
                index = index++ % backWorkerList.size();
                final Worker worker = backWorkerList.get(index);
                poolExecutor.execute(new FrontHandler(channel, worker, processor, encoder, decoder, framerClass));
            }
        } catch (Throwable e) {

            //抛出异常，暂停一秒，继续跑
            e.printStackTrace();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
    }
}
